#include "logicmanager.h"
#include <QTimer>

static const int gPluseIntervalSecs = 35000;

#define PRINT_ENTER_FUN \
qDebug("S:  in LogicManager::%s", __func__)

LogicManager::LogicManager(QObject *parent) :
    QObject(parent)
{
    PRINT_ENTER_FUN;
    mUserList = new QList<userInfo>;
    mTimerList = new QList<QTimer *>;
    mXmlData = new QByteArray;
    mHash = new QHash<QTimer *, int>;
    mXml = new xmlHandle;

    QObject::connect(mXml, SIGNAL(sendLogin(QString, QString)), this, SLOT(onSendLogin(QString, QString)));
    QObject::connect(mXml, SIGNAL(sendLogout(QString)), this, SLOT(onSendLogout(QString)));
    QObject::connect(mXml, SIGNAL(sendPulse(QString)), this, SLOT(onSendPulse(QString)));
}

LogicManager::~LogicManager()
{
    PRINT_ENTER_FUN;
    if (mUserList) {
        mUserList->clear();
        delete mUserList;
    }
    if (mTimerList) {
        for (int i = 0; i < mTimerList->size(); ++i) {
            delete mTimerList->at(i);
        }
        mTimerList->clear();
        delete mTimerList;
    }
    if (mXmlData) {
        delete mXmlData;
    }
    if (mHash) {
        delete mHash;
    }
    if (mXml) {
        delete mXml;
    }
}

void LogicManager::onReceivedData(const QString & ip, const QByteArray & data)
{
    mXml->read(ip, data);
}

void LogicManager::onNotify(const QString & ip, int code)
{
    qDebug("S:  onNotify code: %d", code);
    switch (code) {
        case 0:{
            break;
        }
        default:{
            onSendLogout(ip);
            break;
        }
    }
}

void LogicManager::onSendLogin(QString ip, QString name)
{
    qDebug("S:  in LogicManager::%s, ip:%s", __func__, ip.toLatin1().data());
    if (mUserList->size() != mTimerList->size()) {
        qDebug("S:  %s error logic!!!", __func__);
        return;
    }

    int i = finderUserIndex(ip);

    userInfo info;
    info.setIp(ip);
    info.setName(name);

    if (i >= 0) {
        mUserList->replace(i, info);
        mTimerList->at(i)->start(gPluseIntervalSecs);
        broadcastUserList();

        mXml->statusToXml(*mXmlData, xmlRenameSuccessful);
        emit sendData(ip, *mXmlData);
        //emit rename successful
    } else {
        QTimer * timer = new QTimer;
        qDebug("pluse timer: %d", (int)timer);
        mUserList->append(info);
        mTimerList->append(timer);

        mHash->insert(timer, mUserList->size() - 1);
        QObject::connect(timer, SIGNAL(timeout()), this, SLOT(onPluseTimeout()));
        timer->start(gPluseIntervalSecs);
        broadcastUserList();

        mXml->statusToXml(*mXmlData, xmlLoginSuccessful);
        emit sendData(ip, *mXmlData);
        //emit login successful
    }
}

void LogicManager::onSendLogout(QString ip)
{
    qDebug("S:  in LogicManager::%s, ip:%s", __func__, ip.toLatin1().data());
    int i = finderUserIndex(ip);
        emit sendLogout(ip);
    if (i >= 0) {

        mTimerList->at(i)->stop();
        delete mTimerList->at(i);
        mTimerList->removeAt(i);
        mUserList->removeAt(i);
        broadcastUserList();
    } else {
        //emit logout failed
    }
}

void LogicManager::onSendPulse(QString ip)
{
    qDebug("S:  in LogicManager::%s, ip:%s", __func__, ip.toLatin1().data());
    int i = finderUserIndex(ip);
    if (i >= 0) {
        qDebug("S:  timer:%d, at:%d", mTimerList->at(i), i);
        mTimerList->at(i)->start();
    }
}

void LogicManager::onPluseTimeout()
{
    PRINT_ENTER_FUN;
    QTimer * timer = qobject_cast<QTimer *>(QObject::sender());
    if (timer && mHash->contains(timer)) {
        int i = mHash->value(timer);
        if (i >= 0 && i < mUserList->size()) {
            qDebug("pluse timer: %d removed", (int)timer);
            emit sendLogout(mUserList->at(i).getIp());
            mTimerList->at(i)->stop();
            delete mTimerList->at(i);
            mTimerList->removeAt(i);
            mUserList->removeAt(i);
            broadcastUserList();
        }
    }
}

void LogicManager::broadcastUserList()
{
    mXml->userListToXml(*mXmlData, *mUserList);
    for (int i = 0; i < mUserList->size(); ++i) {
        emit sendData(mUserList->at(i).getIp(), *mXmlData);
    }
}

int LogicManager::finderUserIndex(const QString & ip)
{
    for (int i = 0; i < mUserList->size(); ++i) {
        if (mUserList->at(i).getIp() == ip) {
            return i;
        }
    }
    return -1;
}
